<?php
namespace app\astrologer\lib;

use app\common\lib\apns\ApnsPush;
use think\Config;
use think\Db;
use think\Log;
use XznsTools\cache\CacheManage;
use XznsTools\push\Huawei;
use XznsTools\push\Oppo;
use XznsTools\push\Vivo;
use XznsTools\push\Xiaomi;
use GuzzleHttp\Exception\GuzzleException;

class AstrPush
{
    protected $pushTokenCacheModel = 'push_token'; //huawei=>5 xiaomi=>4 vivo=>3 oppo=>2 极光=> 1
    protected $config = [];

    protected $cacheId = [
        'huawei' => 5,
        'xiaomi' => 4,
        'vivo' => 3,
        'oppo' => 2,
        'jpush' => 1,
    ];

    public function __construct()
    {
        // \think\Log::write('进入个推构造方法：','log',true);
        $this->config = Config::Load(APP_PATH.'astrologer/extra/push.php','push','astrologer');
    }

    /**
     * 向用户推送信息
     * @param $uid
     * @param $alert
     * @param $data
     * @param string $title
     * @return array|mixed
     */
    public function pushUserMsg($uid, $alert, $data, $title = '准了咨询师')
    {
        // 获取用户设备ID
        $userRegidData = (new \app\common\cachemodel\ZlcrAstrPush())->where('astr_id', $uid)->field('status,push_type,regid')->find();
        if (!$userRegidData)
        {   // 未绑定推送
            return ['success' => true];
        } else
        {
            $userRegid = $userRegidData['regid'];
            $pushType = $userRegidData['push_type'];
            if ($userRegidData['status'] == 0)
            {   // 关闭个性化推送 取消个推
                return ['success' => true];
            }
        }

        if ($userRegid)
        {
            $extras = $this->getExtraData($data);
            $pushRecordData = [
                'astr_id' => $uid,
                'content' => $alert,
                'target' => $extras['target'] ?? '',
                'link' => $extras['action'] ?? '',
                'title' => $title,
                'admin_name' => 'api',
                'admin_id' => 0,
                'create_time' => time(),
                'extend' => json_encode($extras, JSON_UNESCAPED_UNICODE),
            ];
            $mid = Db::table('wechat_backup_07_18_14_43_00.zlcr_astr_push_record')->insertGetId($pushRecordData);
            $extras['push_id'] = $mid;
            $extras['push_type'] = '个推';
            $extras['push_content'] = $alert;

            $pushData = [
                'plantform' => $pushType == 1 ? 1 : 3, // 1 => all  2 => IOS 3 => android
                'pushType' => $pushType,
                'regid' => [$userRegid],
                'title' => $title, // 推送标题
                'content' => $alert, // 推送内容
                'extras' => $extras, // 扩展字段
                'informType' => 0, //通知栏样式 0默认 1大文本 2收件箱 3大图片
                'bigText' => '', // 大文本内容
                'bigPicPath' => '', // 大图片路径
                'timeToLive' => 86400, // 默认86400
            ];

            $res = $this->pushOne($pushData);

            if (!isset($res['message']))
            {
                $res['message'] = '未知错误';
            }

            return $res;
        }
        return ['success' => true];
    }

    public function getExtraData($data = [])
    {
        switch ($data['action'])
        {
            case 'extend':
                $extras = [
                    'target' => $data['target'],
                    'link' => $data['link'],
                ];
                break;
            default :
                $extras = [];
                break;
        }

        if (isset($data['pop_msg']))
        {
            $extras['pop_msg'] = $data['pop_msg'];
        }

        return $extras;
    }

    /**
     * 单推推送
     * @param array $data
     *  $data = [
     *      'plantform' => 1, // 1 => all  2 => IOS 3 => android
     *      'pushType' => 1, // 推送方式 huawei=>5 xiaomi=>4 vivo=>3 oppo=>2 极光=> 1
     *      'regid' => [], // 推送用户 array
     *      'title' => '', // 推送标题
     *      'content' => '', // 推送内容
     *      'extras' => '', // 扩展字段
     *      'informType' => 0, //通知栏样式 0默认 1大文本 2收件箱 3大图片
     *      'bigText' => '', // 大文本内容
     *      'bigPicPath' => '', // 大图片路径
     *      'timeToLive' => 86400
     *   ];
     * @return array|mixed
     * @throws GuzzleException
     * @throws \Exception
     */
    public function pushOne($data)
    {
        try
        {
            switch ($data['pushType'])
            {
                case 5: // 华为推送
                    $hwPush = new Huawei($this->config['huawei']);
                    $hwCacheModel = CacheManage::getInstance()->setCacheConfig($this->pushTokenCacheModel, $this->cacheId['huawei']);
                    $token = $hwCacheModel->getCache(); // 缓存
                    if (!$token)
                    {
                        $tokenData = $hwPush->getAccessToken();
                        if ($tokenData['success'])
                        {
                            $token = $tokenData['data']['access_token'];
                            // token 写入缓存
                            $hwCacheModel->setCache($token, 'details', false);
                        } else
                        {
                            return [
                                'success' => false,
                                'message' => '获取推送AccessToken失败',
                            ];
                        }
                    }
                    $res = $hwPush->setData($data)->push($token, $data['regid']);
                    break;
                case 4: // 小米推送
                    $miPush = new Xiaomi($this->config['xiaomi']);
                    $res = $miPush->setData($data)->pushOne($data['regid']);
                    if ($res['result'] === 'ok')
                    {
                        $res['success'] = true;
                    } else
                    {
                        $res['success'] = false;
                    }
                    break;
                case 3: // vivo 推送
                    $vivoPush = new Vivo($this->config['vivo']);
                    $vivoCacheModel = CacheManage::getInstance()->setCacheConfig($this->pushTokenCacheModel, $this->cacheId['vivo']);
                    $token = $vivoCacheModel->getCache(); // 缓存
                    if (!$token)
                    {
                        $tokenData = $vivoPush->getAccessToken();
                        if ($tokenData['success'] && $tokenData['data']['result'] == 0)
                        {
                            $token = $tokenData['data']['authToken'];
                            // token 写入缓存
                            $vivoCacheModel->setCache($token, 'details', false);
                        } else
                        {
                            return [
                                'success' => false,
                                'message' => 'vivo获取推送AccessToken失败',
                            ];
                        }
                    }
                    // Log::write('vivo推送'.var_export($data,true),'error');
                    if (count($data['regid']) > 1)
                    {   // 批量单推
                        $res = $vivoPush->setData($data)->batchPushOne($token, $data['regid']);
                    } else
                    {  //单推
                        $res = $vivoPush->setData($data)->pushOne($token, current($data['regid']));
                    }

                    if (!$res['success'] || $res['data']['result'] != 0)
                    {
                        Log::write('vivo推送失败；错误消息：' . json_encode($res, JSON_UNESCAPED_UNICODE) . ',推送消息：' . json_encode($data, JSON_UNESCAPED_UNICODE), 'error', true);
                        $res = [
                            'success' => false,
                            'message' => json_encode($res, JSON_UNESCAPED_UNICODE),
                        ];
                    }
                    break;
                case 2: // oppo 推送
                    $oppoPush = new Oppo($this->config['oppo']);
                    $oppoCacheModel = CacheManage::getInstance()->setCacheConfig($this->pushTokenCacheModel, $this->cacheId['oppo']);
                    $token = $oppoCacheModel->getCache(); // 缓存
                    if (!$token)
                    {
                        $tokenData = $oppoPush->getAccessToken();
                        if ($tokenData['success'])
                        {
                            $token = $tokenData['data']['data']['auth_token'];
                            // token 写入缓存
                            $oppoCacheModel->setCache($token, 'details', false);
                        } else
                        {
                            return [
                                'success' => false,
                                'message' => '获取推送AccessToken失败',
                            ];
                        }
                    }
                    $res = $oppoPush->setData($data)->batchPushOne($token, $data['regid']);
                    break;
                case 6:
                    //个推
                    //apns推送
                    $apnsPush = new ApnsPush($this->config['apns']);
                    $res = $apnsPush->setData($data)->push($data['regid']);
                    if ((int)$res['http_code'] === 200)
                    {
                        $res['success'] = true;
                    } else
                    {
                        $res['success'] = false;
                    }
                    break;
                default:
                    return ['success' => true];
            }

        }
        catch (\Exception $e)
        {
            Log::write('个推失败[' . $e->getFile() . ':' . $e->getLine() . ']' . PHP_EOL . $e->getMessage(), 'error', true);

            return [
                'success' => false,
                'message' => $e->getMessage(),
            ];
        }

        return $res;
    }
}
